﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Fish.Models;
using Fish.DAL;
using Microsoft.AspNet.Identity;
using System.Security.Cryptography;
using System.Web.Security;

namespace Fish.Controllers
{
    /** 
      * This class is responsible for viewing the responsibilities of each logged in user, registering, and editing of
     * the user profile. It also includes the methods responsible for changing the password of the user and uploading 
     * an image to the user's profile.
     */
    [Authorize]
    public class UsersController : Controller
    {
        private FishContext db = new FishContext();

        // GET: /Users/
        public ActionResult Index()
        {
            return View(db.Users.ToList());
        }

        //GET: /Users/ViewResponsibilities/
        public ActionResult ViewResponsibilities()
        {
            int id = GetLoggedInID();
            List<EventUserRelations> userEvents = db.EventUserRelations.Where(u => u.UsersID == id).ToList();
            List<Responsibilities> responsibilities = new List<Responsibilities>();

            for (int i = 0; i < userEvents.Count(); i++)
            {
                int eventID = userEvents.ElementAt(i).EventsID;
                Events eventX = db.Events.Find(eventID);
                EventInfo eventInfo = db.EventInfoes.Where(e => e.EventsID == eventID).FirstOrDefault();
                DateTime startDate;
                if (eventInfo == null)
                {
                    startDate = new DateTime();
                }
                else
                {
                    startDate = eventInfo.StartDate;
                }
                string eventName = eventX.Name;
                string eventId = eventX.ID.ToString();
                IList<MyTask> tasks = userEvents.ElementAt(i).Tasks;

                for (int j = 0; j < tasks.Count(); j++)
                {
                    string taskString = tasks.ElementAt(j).taskMsg;
                    Responsibilities resp = new Responsibilities();
                    resp.eventName = eventName; resp.eventDate = startDate; resp.task = taskString; resp.eventId = eventId;

                    responsibilities.Add(resp);
                }
            }


            ViewBag.RespList = responsibilities.OrderByDescending(a=>a.eventDate);
            return View();
        }

        //GET: /Users/ChangePassword
        public ActionResult ChangePassword(int? id)
        {
            //id = GetLoggedInID();
            //Users users = db.Users.Find(id);
            //if (users == null)
            //{
            //  return HttpNotFound();
            //}
            //users.Password = "";
            return View();
        }

        /** 
          * This method is responsible for changing the password of the user and updating the
         * database with the new hashed password.
         */
        // POST: /Users/ChangePassword
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ChangePassword(IList<string> serials)
        {
            AccountController ac = new AccountController();
            //string username = User.Identity.GetUserName();
            //Users user = FindUserByUserName(username);
            int userID = int.Parse(Session["userID"].ToString());
            Users user = db.Users.Find(userID);
            string oldPass = serials[0]; string newPass = serials[1]; string newPass2 = serials[2];
            System.Diagnostics.Debug.WriteLine("Username: " + user.Username + " oldPassword: " + serials[0] + " newPass: " + serials[1]);

            if (ac.correctPassword(oldPass, user))
            {
                if (newPass.Equals(newPass2))
                {
                    string salt = ac.CreateSalt(16);
                    user.Salt = salt;
                    string hashedPassword = ac.GenerateSaltedHash(newPass, salt);
                    System.Diagnostics.Debug.WriteLine("Passwords match: " + hashedPassword);
                    user.Password = hashedPassword;
                    db.SaveChanges();
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("NO match: ");
                    ModelState.AddModelError("", "New Passwords do not match");
                    return View();
                }
            }
            else
            {
                ModelState.AddModelError("", "Wrong Password");
                return View();
            }

            return RedirectToAction("Details");
        }

        /** 
        * This method is responsible for getting the logged in user either from the session or
         * using Idententy.Authenticated.
        */
        public int GetLoggedInID()
        {
            int id = -1;

            if (Session != null)
            {
                if (Session["userID"] != null)
                {
                    id = int.Parse(Session["userID"].ToString());
                }
            }

            else
            {
                if (User.Identity.IsAuthenticated)
                {
                    System.Diagnostics.Debug.WriteLine("feeh name");
                    string username = User.Identity.GetUserName();
                    Users us = db.Users.Where(u => u.Username.Equals(username)).FirstOrDefault();
                    id = us.ID;
                }
                else
                {
                    id = -1;
                    FormsAuthentication.SignOut();
                    RedirectToAction("Index", "Home");
                }
            }
            return id;
        }

        // GET: /Users/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                id = GetLoggedInID();
            }
            Users users = db.Users.Find(id);
            if (users == null)
            {
                return HttpNotFound();
            }
            return View(users);
        }

        /** 
         * This method is responsible for viewing the image uploaded by the user to his profile.
         */
        [HttpGet]
        public ActionResult ViewImage(int id)
        {
            System.Diagnostics.Debug.WriteLine("User: " + id);
            Users user = FindUserByUserId(id);
            byte[] buffer = user.UserImage;

            if (buffer == null)
            {
                return new FilePathResult("~/Repository/NoPhoto.jpg", "image/jpg");
            }
            return File(buffer, "image/jpg", string.Format("{0}.jpg", id));
            //return null;

        }

        private Users FindUserByUserId(int d)
        {
            Users user = db.Users.Where(u => u.ID == d).FirstOrDefault();
            return user;
        }

        public Users FindUserByUserName(string username)
        {
            Users user = db.Users.Where(u => u.Username.Equals(username)).FirstOrDefault();
            return user;
        }


        // GET: /Users/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: /Users/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,Username,Password,DateOfBirth,Email,Created,Modified")] Users users)
        {
            if (ModelState.IsValid)
            {
                db.Users.Add(users);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(users);
        }


        /** 
         * This method is responsible for updating the image of the user 
         */
        [HttpPost]
        public ActionResult UpdateImage(HttpPostedFileBase uploadedImage, int id)
        {
            byte[] imageBytes = null;
            if (uploadedImage != null)
            {

                int imageLength = uploadedImage.ContentLength;
                imageBytes = new byte[imageLength];
                uploadedImage.InputStream.Read(imageBytes, 0, imageLength);
            }
            Users usr = db.Users.Find(id);
            usr.UserImage = imageBytes;
            db.Entry(usr).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Edit");

        }
        // GET: /Users/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                if (GetLoggedInID() == -1)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
                else
                {
                    id = GetLoggedInID();
                }
            }
            Users users = db.Users.Find(id);
            if (users == null)
            {
                return HttpNotFound();
            }

            return View(users);
        }

        // POST: /Users/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "ID,Username,Password,DateOfBirth,Email,Created,Modified")] Users users)
        {
            System.Diagnostics.Debug.WriteLine(users.ID + " " + users.Username + " " + users.Password + " " + users.DateOfBirth + " " + users.Email);
            if (ModelState.IsValid)
            {
                db.Entry(users).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Details", "Users");
            }
            return View(users);
        }

        // GET: /Users/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                id = GetLoggedInID();
                if (id == -1)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
            }
            Users users = db.Users.Find(id);
            if (users == null)
            {
                return HttpNotFound();
            }
            return View(users);
        }

        // POST: /Users/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Users users = db.Users.Find(id);
            db.Users.Remove(users);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
